ViewModel for Business

A common problem is when the User Interface (UI) code fills up with unnecessary business logic. This logic is often regarded as a quick fix and the developer has every intention to someday return and clean it up by refactoring the code such that the business rules are handled by the model and the UI handles the user interaction only. In reality, this never happens. I have never seen a team have enough room in their schedule to go back and redo work the client considers already done, delivered, and paid for.

Every developer knows that the degrees of freedom rapidly decrease once you fill your UI with business logic:

  1. You cannot easily reuse the logic placed in a UI so you copy it and increase the maintenance.
  2. You forget about rules placed in the UI so your system takes on a life of its own.
  3. Once you have logic in the UI, you cannot be expected to know it all so you become afraid to make changes to your system because something will or may break.
  4. You dare not give the UI to that brilliant designer because that designer will break the logic for sure.

Regardless, I see business logic in the UI everywhere I go. When I ask about it, I always get answers like: “Well, this is not finished yet”; “Well, this is really special stuff, only used in one place”, or “Yeah, I know it sucks, I will fix that later”. But “later” never comes, does it? It will always be “later”.

I am certainly no Superman – I see business logic in UI code I have written myself too. If everyone - or at least most of us - is getting into these situations, could it be possible that we are doing things the wrong way? Could it be that doing things the right way is a bit too complicated?

Strategies

These are some strategies to help developers do the correct thing and follow the coding guidelines:

  1. Automated review tools like FxCop
  2. Adhering strictly to ModelView patterns as MVVC or MVC – though, you still need to verify that you follow the pattern.
  3. Peer review (that usually will be done “later”)
  4. Some other strategy that will force violators (you and me) to mend our ways – even if the correct way is complicated
  5. Make it easier and faster to follow the “coding guidelines” to be quick and dirty.

It is no surprise that I am in favor of making things easier. To do that, we need to understand what causes things to go wrong in the first place. Why is the UI filling up with business logic? There are a couple of reasons, depending on how far you are from being model-driven. Some of these reasons will apply:

  1. The UI will need to transform data (could be business logic) and display it according to specification.
  2. Actions performed in UI act on selections from UI components that have data in the transformed presentation format and need to be transformed back (could be business logic) to model-scope to let the model work on the data (business logic). Also, check that the parameters sent to the model method are valid (could be business logic).
  3. The existing business logic may not match 100% what your action should do, you may want to call two, three, or more methods to get the job done (new business logic) and you may want to do some small checks based on the results of each method (could be business logic).
  4. Validation – your UI will do a lot of small checks to see that the data fulfills the overall rules for your application (business logic).

How do we make these reasons go away?

  • We do it by offering a good and easy way to transform model elements (or data if you will) into data elements suitable for rendering to match the specification.
  • We do it by making it easy to add business logic where it belongs (in the model) and making it effortless to call it.
  • We offer a clean and simple way to add validation logic.

By setting the model in focus and making it simple to add methods, derived attributes, and derived associations, you can do everything you need for a specific UI in the model. This is an improvement, even if it is not the solution. The problem is: if you have 100 UIs, your model is filled with 100 times derived attributes and derived links. That does not sound like a good thing. It will eventually become difficult to see the trees for the forest in a model like that. Furthermore, when a UI is dropped and deleted for some reason, will we remember to drop the derived associations and derived attributes we added to the model to accommodate it? Probably not.

A transformation layer between the UI and the model can fix this. The transformation layer is allowed to have business logic, as long as it is unique for the context it works within. If the logic is not unique, it should go into the model, ready to be re-used. We call this transformation Layer for a ViewModel. The name View-Model comes from this being a particular view or perspective into how to look at the model. The perspective often correlates to UI views.

ViewModels

A ViewModel transforms a piece of the model for a specific purpose. The purpose is often, but not always, to prepare the model information for interaction with a user for a specific use case – a UI. It can also be useful for creating data transfer objects suitable for exposure for another application or system or some reporting engine.

Why is it better to have the rules in a ViewModel than in the UI? There are several reasons:

  1. Testing. It is good to test the logic separate from the UI because it is awkward and error-prone to test and read the results back from the UI.
  2. ViewModel re-use. You may have different UIs for the same use case (beginner/advanced, Web-API/Rich client, etc).
  3. Design time type checking. Most UI-binding strategies rely on using strings that can only be checked at runtime (this is true for Winforms and ASP.NET – MVC with Razor is type-checked and also WPF), whereas a good ViewModel is type-checked at design or compile time.
  4. Logic. When important logic is in the ViewModel, the designers can work on the UI without risking any damage to the logic.
  5. If we have dedicated designers, we will not want to wait for them to release a UI file to fix the business logic within.
  6. The UI may be on the other side of a network (another physical tier) so the UI cannot have access to the domain layer tier.
  7. UI and logic have very different motivators. Hence, they will often change for varying reasons (looking good versus working correctly). Mixing them up adds confusion regarding the distinction between these important aspects.
  8. Security. Designers that have access to the ViewModel cannot go beyond the ViewModel and unintentionally expose confidential information in the use case at hand.

You do not have to use a ViewModel pattern to create a great application. Rather, it is a good idea to use the ViewModel pattern when building applications that are going to be worked on for a long time and released in several versions over several iterations. These will most likely see different developers and UI designers and may very well be radically changed with regard to presentation framework during its lifespan. In short, it is always advantageous for successful applications to use a ViewModel pattern.

Check out a detailed technical definition of the ViewModel itself: The Declarative ViewModel

Video tutorials

This page was edited 22 days ago on 11/01/2024. What links here